#include "Animation.h"
#include "Frame.h"
#include "tinyxml.h"

//#include "SGD Wrappers\CSGD_TextureManager.h"

Animation::Animation()
{
	pTM = nullptr;
	pTM = CSGD_TextureManager::GetInstance();

	curFrame		= 0;
	maxFrames		= 0;
	timeWaited		= 0.0f;
	isPlaying		= false;
	isLooping		= false;
	playSpeed		= 1.0f;
}

Animation::~Animation()
{
	pTM = nullptr;
}

void Animation::Initialize(std::vector<Frame*> frames, std::wstring name)
{
	frameArray		= frames;
	curFrame		= 0;
	maxFrames		= frameArray.size();
	timeWaited		= 0.0f;
	isPlaying		= false;
	isLooping		= false;
	playSpeed		= 1.0f;
	fileName		= name;

	imageID = CSGD_TextureManager::GetInstance()->LoadTexture(fileName.c_str());
}

bool Animation::LoadAnimationFromFile(std::string file)
{
	curFrame		= 0;
	timeWaited		= 0.0f;
	isPlaying		= false;
	isLooping		= false;
	playSpeed		= 1.0f;

	TiXmlDocument doc;

	if( doc.LoadFile(file.c_str()) == false )
		return false;

	TiXmlElement* root = doc.RootElement();
	if( root == nullptr )
		return false;

	TiXmlElement* animation = root->FirstChildElement( "FileName" );

	double time;

	if(animation->Attribute("playSpeed", &time) == nullptr)
		time = 0;

	playSpeed = time;

	const char* tmpString = animation->GetText();
	WCHAR tmpW[100];
	mbstowcs_s(nullptr, tmpW, 100, tmpString, _TRUNCATE);
	fileName = tmpW;

	imageID = CSGD_TextureManager::GetInstance()->LoadTexture(fileName.c_str());

	animation = animation->NextSiblingElement( "Frame" );

	while( animation != nullptr )
	{
		int tmpX = 0;
		int tmpY = 0;
		int width = 0;
		int height = 0;
		int tmpAX = 0;
		int tmpAY = 0;
		int rectX1 = 0;
		int rectX2 = 0;
		int rectY1 = 0;
		int rectY2 = 0;
		double time = 0;
		tVector2D aPoint;

		if( animation->Attribute( "x", &tmpX ) == nullptr )
			tmpX = 0;

		if( animation->Attribute( "y", &tmpY ) == nullptr )
			tmpY = 0;

		if( animation->Attribute( "width", &width ) == nullptr )
			width = 0;

		if( animation->Attribute( "height", &height ) == nullptr )
			height = 0;

		if( animation->Attribute( "time", &time ) == nullptr )
			time = 0;

		if( animation->Attribute( "aPointX", &tmpAX ) == nullptr )
			tmpAX = 0;

		if( animation->Attribute( "aPointY", &tmpAY ) == nullptr )
			tmpAY = 0;

		if( animation->Attribute( "rx1", &rectX1 ) == nullptr )
			height = 0;

		if( animation->Attribute( "rx2", &rectX2 ) == nullptr )
			time = 0;

		if( animation->Attribute( "ry1", &rectY1 ) == nullptr )
			tmpAX = 0;

		if( animation->Attribute( "ry2", &rectY2 ) == nullptr )
			tmpAY = 0;

		RECT tmpRect = {rectX1, rectY1, rectX2, rectY2};

		aPoint.fX = tmpAX;
		aPoint.fY = tmpAY;
		
		Frame* tmp = new Frame;
		tmp->Init(tmpX, tmpY, width, height, time, aPoint, tmpRect);

		frameArray.push_back(tmp);

		animation = animation->NextSiblingElement( "Frame" );
	}
	maxFrames = frameArray.size();

	return true;
}

void Animation::SaveAnimationtoFile(std::string file)
{
	TiXmlDocument doc;
	TiXmlDeclaration* dec = new TiXmlDeclaration("1.0", "utf-8", "");
	doc.LinkEndChild(dec);
	TiXmlElement* root = new TiXmlElement("Animation");
	doc.LinkEndChild(root);

	TiXmlElement* fName = new TiXmlElement("FileName");

	fName->SetAttribute("playSpeed", playSpeed);

	char tmpString[100];
	WCHAR tmpW[100];
	wcscpy_s(tmpW, fileName.c_str());
	wcstombs_s(nullptr, tmpString, 100, tmpW, _TRUNCATE );
	TiXmlText* text = new TiXmlText(tmpString);
	fName->LinkEndChild(text);
	root->LinkEndChild(fName);

	for(int i = 0; i < frameArray.size(); ++i)
	{
		TiXmlElement* frame = new TiXmlElement("Frame");

		frame->SetAttribute("x", frameArray[i]->GetXPos());
		frame->SetAttribute("y", frameArray[i]->GetYPos());
		frame->SetAttribute("width", frameArray[i]->GetWidth());
		frame->SetAttribute("height", frameArray[i]->GetHeight());
		frame->SetAttribute("time", frameArray[i]->GetTime());
		frame->SetAttribute("aPointX", frameArray[i]->GetAPoint().fX);
		frame->SetAttribute("aPointY", frameArray[i]->GetAPoint().fY);
		frame->SetAttribute("rx1", frameArray[i]->GetColRect().left);
		frame->SetAttribute("rx2", frameArray[i]->GetColRect().right);
		frame->SetAttribute("ry1", frameArray[i]->GetColRect().top);
		frame->SetAttribute("ry2", frameArray[i]->GetColRect().bottom);

		root->LinkEndChild(frame);
	}
	doc.SaveFile(file.c_str());
}

void Animation::Update(float elapsed)
{
	if(!isPlaying)
		return;

	timeWaited += elapsed * playSpeed;

	if(timeWaited > frameArray[curFrame]->GetTime())
	{
		++curFrame;
		timeWaited = 0.0f;

		if(curFrame >= maxFrames)
		{
			if(isLooping)
				curFrame = 0;
			else
			{
				isPlaying = false;
				curFrame = 0;
			}
		}
	}
}

void Animation::Render(int x, int y, float scale, DWORD color, bool isFlipped)
{
	RECT tile = frameArray[curFrame]->GetRect();

	float scaleX = scale;

	if(isFlipped)
	{
		scaleX = -scaleX;
		
		int width = tile.right - tile.left;

		x += width * scale;
	}

	pTM->Draw(imageID, (x - frameArray[curFrame]->GetAPoint().fX) + frameArray[0]->GetWidth() / 2,
		(y - frameArray[curFrame]->GetAPoint().fY) + frameArray[0]->GetHeight(),
		scaleX, scale, &tile, 0, 0, 0, color);
	
}

void Animation::Play(bool looping, float speed)
{
	if(speed != 0)
		playSpeed = speed;
	curFrame = 0;
	timeWaited = 0.0f;
	isPlaying = true;
	isLooping = looping;
}

void Animation::Stop()
{
	isPlaying = false;
}

void Animation::Resume()
{
	isPlaying = true;
}
